#ifndef ECADDATABASE_H
#define ECADDATABASE_H

#include <QObject>
#include <QMap>

#include "Ipc2581.h"
#include "ECad.h"
#include "Layer.h"
#include "Step.h"
#include "Component.h"
#include "Package.h"

namespace Ipc2581b
{
    class Component;
    class Layer;
    class PadstackDef;
    class Package;
    class Pin;
    class PinRef;
    class Stackup;
    class Step;

    // Maybe return QAIModel or Object wrapper that ease querying/exploring content
    // As well this could be the inerface that hide the generated classes.

    // XML -> generated Ipc2581b classes -> Unified Iface for Qt Model/View and Qt Scene/View
    // We will have to do the same for Logistic, History, Bill of material and Approved vendors
    class EcadDatabase : public QObject
    {
        Q_OBJECT
    public:
        explicit EcadDatabase(QObject *parent = 0);

        /*
         *  EcadHEader
         */
        // Units
        // SpecById
        // ChangeRecList

        /*
         * EcadData
         */
        const Layer *layerById(const QString &id) const;
        const Stackup *stackupById(const QString &id) const;
        const Step *stepById(const QString &id) const;
        // DxfMeasurementsById

        /*
         *  ECadData.StepList
         */

        // units, datum, profile

        // NonStandardAttribute by id
        // PadstackById
        // RouteById
        // LogicalNetById
        // PhynetGroupById
        // LayerFeatureSetByLayerId

        const PadstackDef *padstackDefById(const QString &id) const;
        const Package *packageById(const QString &id) const;
        const Component *componentById(const QString &id) const;

        // Advanced lookup

        const Pin *pinByPinRef(const PinRef *pinRef) const;
        const Package *packageByPinRef(const PinRef *pinRef) const;
        const Component *componentByPinRef(const PinRef *pinRef) const;

    signals:

    public slots:
    };

    class StepResolver;
    class ComponentResolver;
    class PackageResolver;
    class PadResolver;

    class EcadResolver
    {
    public:
        EcadResolver(const Ipc2581 *ipc);

        QList<QString> layerIds() const;
        const Layer *layer(const QString &id) const;

        QList<QString> stackupIds() const;
        const Stackup *stackup(const QString &id) const;
        //const StackupResolver *stackup(const QString &id) const;

        QList<QString> stepIds() const;
        const Step *step(const QString &id) const;
        const StepResolver *stepResolver(const QString &id) const;

    private:
        QMap<QString, const Layer *> m_layerMap;
        QMap<QString, const Stackup *> m_stackupMap;
        QMap<QString, const Step *> m_stepMap;
        QMap<const Step*, StepResolver *> m_stepResolverMap;
    };

    class StepResolver
    {
    public:
        StepResolver(const EcadResolver *ecadResolver, const Step *step);

        const Layer *layer(const QString &id) const
        {
            return m_ecadResolver->layer(id);
        }

        const Component *component(const QString &id) const;
        const ComponentResolver *componentResolver(const QString &id) const;
        const Package *package(const QString &id) const;
        const PackageResolver *packageResolver(const QString &id) const;

    private:
        EcadResolver *m_ecadResolver;
        const Step *m_step;

        QMap<QString, const Component *> m_componentMap;
        QMap<const Component*, ComponentResolver> m_componentResolverMap;
        QMap<QString, const Package *> m_packageMap;
        QMap<const Component*, PackageResolver *> m_packageResolverMap;

    };

    class PackageResolver
    {
    public:
        PackageResolver(const StepResolver *stepResolver, const Package *package):
            m_stepResolver(stepResolver),
            m_package(package)
        {

        }

        const Pin* pin(const QString &id);
        const Pad* padForPin(const QString &pinId);
        QList<const Pad*> pads() const;

    private:
        const StepResolver *m_stepResolver;
        const Package *m_package;
    };

    class ComponentResolver
    {
    public:
        ComponentResolver(const StepResolver *stepResolver, const Component *component):
            m_stepResolver(stepResolver),
            m_component(component)
        {
            m_packageResolver = m_stepResolver->packageResolver(m_component->packageRef);
        }

        const Component *component() const
        {
            return m_component;
        }

        const Layer *layer() const
        {
            return m_stepResolver->layer(m_component->layerRef);
        }

        const Package *package() const
        {
            return m_stepResolver->package(m_component->packageRef);
        }

        QList<const Pad*> pads() const
        {
            return m_packageResolver->pads();
        }

    private:
        const StepResolver *m_stepResolver;
        const Component *m_component;
        const PackageResolver *m_packageResolver;

    };

    class PadResolver
    {
    public:
        PadResolver(const StepResolver *stepResolver, const Pad *pad, const Layer *layer):
            m_stepResolver(stepResolver),
            m_pad(pad),
            m_layer(layer)
        {
        }

        const PadstackDef *padstackDef()
        {

        }

        const PadstackPadDef *padstackPadDef(PadUse use)
        {

        }

    private:
        const StepResolver *m_stepResolver;
        const Pad *m_pad;
        const Layer *m_layer;
    };

}
#endif // ECADDATABASE_H
